package fr.inserm.u915.organifooyi.web;

import java.util.AbstractList;
import java.util.Collection;
import java.util.RandomAccess;
import java.util.regex.Pattern;

import fr.inserm.u915.organifooyi.lang.Cast;


public class Path  extends AbstractList<String> implements RandomAccess
	{
	private String tokens[];
	
	private Path()
		{
		this.tokens=new String[]{};
		}
	
	public Path(String pathInfo)
		{
		this();
		if(pathInfo!=null)
			{
			if(pathInfo.startsWith("/")) pathInfo=pathInfo.substring(1);
			this.tokens=pathInfo.split("[/]+");
			}
		}
	
	public boolean startsWith(Object...path)
		{
		return equals(0,path);
		}
	
	private static boolean _equals(String pathItem, Object o)
		{
		if(o==null || "*".equals(o) || (o.getClass()==Character.class && o == (Character)'*'))
			{
			return true;
			}
		else if(o.getClass().isArray())
			{
			Object array[]=(Object[])o;
			for(Object o2:array)
				{
				if(_equals(pathItem,o2)) return true;
				}
			return false;
			}
		else if(o instanceof Collection<?>)
			{
			Collection<?> array=(Collection<?>)o;
			for(Object o2:array)
				{
				if(_equals(pathItem,o2)) return true;
				}
			return false;
			}
		else if(o instanceof Pattern)
			{
			Pattern p=(Pattern)o;
			if(!p.matcher(pathItem).matches()) return false; 
			}
		else if(o.getClass().isEnum())
			{
			if(!Enum.class.cast(o).name().equals(pathItem)) return false;
			}
		else if(o.getClass()==Class.class)
			{
			Class<?> clazz=Class.class.cast(o);
			if(!_isA(pathItem,clazz)) return false;
			}
		else
			{
			if(!String.valueOf(o).equals(pathItem)) return false;
			}
		return true;
		}
	
	public boolean equals(int offset,Object...path)
		{
		for(int i=0;i< path.length;++i)
			{
			Object o=path[i];
			if(!_equals(get(i+offset),o)) return false;
			}
		return true;
		}
	
	public boolean endsWith(String basename)
		{
		if(isEmpty()) return false;
		String last=get(size()-1);
		if(last.equals(basename)) return true;
		int dot=last.lastIndexOf('.');
		if(dot!=-1) last=last.substring(0,dot);
		return last.equals(basename);
		} 
	
	/**
	 * @return index-th value or an empty string  
	 */
	@Override
	public String get(int index)
		{
		return (index<tokens.length?tokens[index]:"");
		}
	
	public <T> boolean isA(int index,Class<T> clazz)
		{
		return get(index,clazz)!=null;
		}
	
	public static <T> T _cast(String text,Class<T> clazz)
		{
		return Cast.cast(text,clazz);
		}
	
	private static <T> boolean _isA(String text,Class<T> clazz)
		{
		return _cast(text,clazz)!=null;
		}
	
	public <T> T get(int index,Class<T> clazz)
		{
		return _cast(get(index),clazz);
		}
	
	public Path popFront()
		{
		if(tokens.length==0) return this;
		Path p=new Path();
		p.tokens=new String[tokens.length-1];
		System.arraycopy(this.tokens,1,p.tokens,0, p.tokens.length-1);
		return p;
		}
	
	@Override
	public int size()
		{
		return this.tokens.length;
		}
	
	public final int getSize()
		{
		return this.size();
		}
	
	public String getPathInfo()
		{
		StringBuilder b=new StringBuilder();
		for(int i=0;i< size();++i)
			{
			if(i!=0) b.append("/");
			b.append(get(i));
			}
		return b.toString();
		}
	
	@Override
	public String toString()
		{
		return getPathInfo();
		}
	}
